package com.hbnu.tools;
import com.hbnu.entity.ShareStat;
import com.hbnu.entity.User;
import com.hbnu.entity.UserFile;
import com.hbnu.enums.Status;
import com.hbnu.web.Client;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static com.hbnu.tools.FileTool.formatFileSize;

public class PrintTool {
    public static void print(String s){
        System.out.print(s);
    }
    public static void println(Object s){
        System.out.println(s);
    }

    static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
    //统一时间输出风格
    public static String getTime(LocalDateTime localDateTime){
        return formatter.format(localDateTime);
    }
    //问好
    public static String printGreeting() {
        // 获取当前时间
        LocalTime currentTime = LocalTime.now();

        // 获取当前小时数
        int hour = currentTime.getHour();

        // 根据不同的时间段打印不同的问候语
        if (hour < 11) {
            return "Good morning, ";
        } else if (hour < 14) {
            return"Good noon, ";
        } else if (hour < 18) {
            return"Good afternoon, ";
        } else {
            return "Good evening, ";
        }
    }

    public static void initPrint(){
        println("Welcome to the " + Status.LOGO +" monitor!\n");
        println("      _    _ ____  _   _ _    _            .-~~~-.\n" +
                "     | |  | |  _ \\| \\ | | |  | |     .-~~'     __  `~~-.\n" +
                "     | |__| | |_) |  \\| | |  | |    /       .-~  ~-.     \\\n" +
                "     |  __  |  _ <| . ` | |  | |   |     .-'        `-.   |\n" +
                "     | |  | | |_) | |\\  | |__| |    \\   /              \\ /\n" +
                "     |_|  |_|____/|_| \\_|\\____/      `-.~ ._ .,., ,..~-'\n");
        println("Copyright (c) Q and/or its affiliates.[version: "+ Status.Version+"]");
    }
    public static void welcome(User user){
        PrintTool.println("Your last login time was "+getTime(user.getLogon_time()));
        PrintTool.println("");
        PrintTool.println("\t\t(^_^): "+printGreeting()+ user.getName()+"!");
        PrintTool.println("");
    }



    //登录错误打印
    public static void logonError(int status){
        String desc=null;
        switch (status){
            case Status.NULL_PASS->desc="密码不能为空";
            case Status.NO_EXIST_USER->desc="用户不存在";
            case Status.ERR_PASS->desc="密码错误";
        }
        println(desc);
    }
    //命令行错误打印
    public static void error(String line,int status){
        String desc=null;
        switch (status){
            case Status.NO_CMD->desc="未找到命令";
            case Status.NULL_PASS->desc="密码不能为空";
            case Status.NO_EXIST_USER->desc="用户不存在";
            case Status.ERR_PASS->desc="密码错误";
            case Status.ERR_PATH->desc="路径错误";
            case Status.EXISTS_FOLDER_NAME->desc="文件夹已存在";
            case Status.ERR_CREATE_FOLDER->desc="文件夹创建失败";
            case Status.ERR_UPDATE->desc="修改异常";
            case Status.ERR_MYSQL->desc="数据库异常";
        }
        println("-bash: "+line+": "+desc);
    }

    //ls
    private static final int TERMINAL_WIDTH = 100; // Windows默认终端宽度

    //映射表
    private static Map<Integer, UserFile> userFileMap;
    //获得子文件数组 已经判断过了是文件夹
    private static UserFile[] getUserFiles(UserFile userFile){
        List<Integer> list = userFile.getList();
        UserFile[] userFiles =new UserFile[list.size()];
        int i=0;
        for (Integer integer : list) {
            userFiles[i++]= userFileMap.get(integer);
        }
        // 排序：目录在前，文件在后，同类型按字母顺序排序
        Arrays.sort(userFiles, (f1, f2) -> {
            if (!f1.is_file() && f2.is_file()) {
                return -1;
            } else if (f1.is_file() && !f2.is_file()) {
                return 1;
            } else {
                return f1.getFname().compareToIgnoreCase(f2.getFname());
            }
        });
        return userFiles;
    }

    //ls
    public static void printLS(UserFile userFile) {
        userFileMap= Client.idUserFileMap;
        UserFile[] userFiles =getUserFiles(userFile);

        // 获取最长文件名的显示宽度
        int maxWidth = 0;
        for (UserFile file : userFiles) {
            int width = getStringDisplayWidth(file.getFname());
            maxWidth = Math.max(maxWidth, width);
        }

        // 计算列数和填充宽度
        int minColumnWidth = maxWidth + 2;  // 文件名宽度 + 2个空格
        int columns = Math.max(1, TERMINAL_WIDTH / minColumnWidth);//个数
        int paddingWidth = TERMINAL_WIDTH / columns;

        // 计算行数
        int rows = (int) Math.ceil((double) userFiles.length / columns);

        // 打印文件
        for (int row = 0; row < rows; row++) {
            for (int col = 0; col < columns; col++) {
                int index = col * rows + row;
                if (index < userFiles.length) {
                    printFileName(userFiles[index], paddingWidth);
                }
            }
            System.out.println();
        }
    }
    //长度
    private static int getStringDisplayWidth(String str) {
        int width = 0;
        for (char c : str.toCharArray()) {
            // 使用 Character.UnicodeScript 判断是否为 CJK 字符 中文字符宽度为2 其他字符宽度为1
            width += (Character.isIdeographic(c) ||
                    Character.UnicodeScript.of(c) == Character.UnicodeScript.HAN)?2:1;
        }
        return width;
    }
    //打印名字+空格数
    private static void printFileName(UserFile userFile, int paddingWidth) {
        String fileName = userFile.getFname() + (userFile.is_file() ? "" : "/");
        System.out.print(padRight(fileName,paddingWidth));
    }
    private static String padRight(String s, int width) {
        // 计算需要补充的空格数
        int actualWidth = getStringDisplayWidth(s);
        int padSize = width - actualWidth;

        return s + " ".repeat(padSize);
    }

    //打印list
   // private final static String[] headers = {"ID", "名称", "类型"};
    public static void printList( UserFile rootFile) {
        String[] headers = {"ID", "名称", "类型"};
        // head的默认宽带
        int[] maxWidths = {2, 4, 4};
        List<Integer> list = rootFile.getList();
        List<String[]> data = new ArrayList<>();
        // 遍历数据计算每列最大显示宽度
        int i=0;
        for (Integer id:list) {
            UserFile userFile = Client.idUserFileMap.get(id);
            String[] s=new String[]{String.valueOf(id), userFile.getFname(),userFile.is_file()?"文件":"文件夹"};
            for (int j = 0; j < 3; j++) {
                maxWidths[j] = Math.max(maxWidths[j], getStringDisplayWidth(s[j]));
            }
            //将文件夹放前面
            if(!userFile.is_file()) {
                data.add(i++,s);
            }else data.add(s);
        }

        printGeneral(headers,maxWidths,data);
    }
    //打印分享表
    public static void printShareList( List<ShareStat> shareList){
        String[] headers = {"ID","提取码", "密码", "到期时间","存储空间"};
        // head的默认宽带
        int[] maxWidths = {2,6, 4, 8, 8};
        List<String[]> data = new ArrayList<>();
        // 遍历数据计算每列最大显示宽度
        for (ShareStat shareStat:shareList) {
            String pwd = shareStat.getPwd();
            pwd=pwd.isEmpty()?"无":pwd;
            String size=formatFileSize(shareStat.getSize());
            String[] s=new String[]{String.valueOf(shareStat.getId()),shareStat.getUuid(), pwd,getTime(shareStat.getTime()),size};
            for (int i = 0; i < 5; i++) {
                maxWidths[i] = Math.max(maxWidths[i], getStringDisplayWidth(s[i]));
            }
            data.add(s);
        }
        printGeneral(headers,maxWidths,data);

    }
    //打印搜索表
    public static void printSelectList( List<UserFile> userFileList){
        String[] headers = {"ID","文件名","地址","类型"};
        // head的默认宽带
        int[] maxWidths = {2, 6, 4,4};
        List<String[]> data = new ArrayList<>();
        // 遍历数据计算每列最大显示宽度
        for (UserFile userFile:userFileList) {
            String[] s=new String[]{String.valueOf(userFile.getFid()),userFile.getFname(),userFile.getPath(),userFile.is_file()?"文件":"文件夹"};
            for (int i = 0; i < 4; i++) {
                maxWidths[i] = Math.max(maxWidths[i], getStringDisplayWidth(s[i]));
            }
            data.add(s);
        }
        printGeneral(headers,maxWidths,data);

    }
    //打印设置表
    public static void printSet(){
        String[] headers = {"ID","名称","地址"};
        // head的默认宽带
        int[] maxWidths = {2,10,4};
        List<String[]> data = new ArrayList<>();
        //
        data.add(new String[]{"1","下载文件", Status.def_ClientPath});
        data.add(new String[]{"2","面对面传输", Status.ftf_SavePath});
        data.add(new String[]{"3","扫码上传", Status.http_SavePath});
        // 遍历数据计算每列最大显示宽度
        for (String[] s:data) {
            maxWidths[2] = Math.max(maxWidths[2], getStringDisplayWidth(s[2]));
        }
        printGeneral(headers,maxWidths,data);
    }
    public static void printGeneral(String[] headers,int[] maxWidths, List<String[]> data) {
        // 打印表头分隔线
        printSeparator(maxWidths);
        // 打印表头
        System.out.print("|");
        for (int i = 0; i < headers.length; i++) {
            print(" " + padRight(headers[i], maxWidths[i]) + " |");
        }
        System.out.println();

        // 打印表头分隔线
        printSeparator(maxWidths);

        // 打印数据
        for (String[] row : data) {
            System.out.print("|");
            for (int i = 0; i < headers.length; i++) {
                print(" " + padRight(row[i], maxWidths[i]) + " |");
            }
            System.out.println();
        }

        // 打印底部分隔线
        printSeparator(maxWidths);
    }
    //答应边框
    private static void printSeparator(int[] widths) {
        System.out.print("+");
        for (int width : widths) {
            System.out.print("-".repeat(width + 2) + "+");
        }
        System.out.println();
    }



    //打印树结构
    private static final String PIPE = "│   ";
    private static final String MIDDLE_ITEM = "├── ";
    private static final String LAST_ITEM = "└── ";
    private static final String EMPTY_SPACE = "    ";

    private static boolean isId;
    public static void printUserFileTree(UserFile userFile) {
        isId=false;
        userFileMap= Client.idUserFileMap;
        printTree(userFile);
    }
    public static void printIdTree(UserFile userFile) {
        isId=true;
        userFileMap= Client.idUserFileMap;
        printTree(userFile);
    }
    //分享树
    public static void printShareTree(UserFile userFile,Map<Integer, UserFile> map) {
        userFileMap=map;
        printTree(userFile);
    }

    public static void printTree(UserFile userFile) {
        //root
        println(userFile.getFname() +"/");
        //DFS遍历
        printUserFileTree(userFile, "");
    }

    private static void printUserFileTree(UserFile userFile, String prefix) {
        //进来的一定有子内容
        UserFile[] userFiles =getUserFiles(userFile);

        for (int i = 0; i < userFiles.length; i++) {
            UserFile file = userFiles[i];
            boolean isLast = (i == userFiles.length - 1);//最后一个

            // 打印当前文件或目录
            System.out.print(prefix);
            System.out.print(isLast ? LAST_ITEM : MIDDLE_ITEM);//"|- 或 └──"
            if(isId)
                System.out.println(file.getFname() +"("+file.getFid()+")"+ (file.is_file() ? "" : "/"));
            else
                System.out.println(file.getFname() + (file.is_file() ? "" : "/"));

            // 递归打印子其内容
            if (file.hasChildren()) {
                String newPrefix = prefix + (isLast ? EMPTY_SPACE : PIPE);
                printUserFileTree(file, newPrefix);
            }
        }
    }


}
